﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TaskFactory.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Factory for tasks
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Threading
{
    using System;
    using EventPattern;

   /// <summary>
   /// Factory for tasks
   /// </summary>
   /// <remarks>
   /// In C# 4.0 type inference has been improved and there is generally no need 
   /// to specify arguments in the  <see cref="FromAsync"/> methods.
   /// </remarks>
   public class TaskFactory
   {
      #region Fields

      private readonly TaskScheduler _scheduler;

      #endregion

      public TaskFactory(TaskScheduler schedular)
      {
         _scheduler = schedular;
      }
      
      public TaskScheduler Scheduler
      {
         get { return _scheduler; }
      }
     
      public ITask<TReturn> FromAsync<TReturn>(
         BeginAsyncMethod begin, EndAsyncMethod<TReturn> end)
      {
         return new Task<TReturn>(
            TaskBinding.FromAsync(begin, end), Scheduler);
      }
      
      public ITask<TReturn> FromAsync<TArg1, TReturn>(
         BeginAsyncMethod<TArg1> begin, EndAsyncMethod<TReturn> end, TArg1 arg1)
      {
         return new Task<TReturn>(
            TaskBinding.FromAsync((c, u) => begin(arg1, c, u), end), Scheduler);
      }

      public ITask<TReturn> FromAsync<TArg1, TArg2, TReturn>(
         BeginAsyncMethod<TArg1, TArg2> begin, EndAsyncMethod<TReturn> end,
         TArg1 arg1, TArg2 arg2)
      {
         return new Task<TReturn>(
            TaskBinding.FromAsync((c, u) => begin(arg1, arg2, c, u), end), Scheduler);
      }

      public ITask<TReturn> FromAsync<TArg1, TArg2, TArg3, TReturn>(
         BeginAsyncMethod<TArg1, TArg2, TArg3> begin, EndAsyncMethod<TReturn> end, 
         TArg1 arg1, TArg2 arg2, TArg3 arg3)
      {
         return new Task<TReturn>(
            TaskBinding.FromAsync((c, u) => begin(arg1, arg2, arg3, c, u), end), Scheduler);
      }
      
      #region Async Actions

      public ITask FromAsync(
         BeginAsyncMethod begin, EndAsyncMethod end)
      {
         return new Task(TaskBinding.FromAsync(begin, end), Scheduler);
      }
      
      public ITask FromAsync<TArg1>(
         BeginAsyncMethod<TArg1> begin, EndAsyncMethod end, TArg1 arg1)
      {
         return new Task(TaskBinding.FromAsync(
            (c, u) => begin(arg1, c, u), end), Scheduler);
      }

      public ITask FromAsync<TArg1, TArg2>(
         BeginAsyncMethod<TArg1, TArg2> begin, EndAsyncMethod end, 
         TArg1 arg1, TArg2 arg2)
      {
         return new Task(TaskBinding.FromAsync(
            (c, u) => begin(arg1, arg2, c, u), end), Scheduler);
      }
      
      public ITask FromAsync<TArg1, TArg2, TArg3>(
         BeginAsyncMethod<TArg1, TArg2, TArg3> begin, EndAsyncMethod end, 
         TArg1 arg1, TArg2 arg2, TArg3 arg3)
      {
         return new Task(TaskBinding.FromAsync(
            (c, u) => begin(arg1, arg2, arg3, c, u), end), Scheduler);
      }

      #endregion

      #region Functions

      public ITask<TReturn> From<TReturn>(Func<TReturn> func)
      {
         return From(func, null);
      }

      public ITask<TReturn> From<TArg1, TReturn>(Func<TArg1, TReturn> func, TArg1 arg1)
      {
         return From(() => func(arg1), null);
      }

      public ITask<TReturn> From<TArg1, TArg2, TReturn>(
         Func<TArg1, TArg2, TReturn> func, TArg1 arg1, TArg2 arg2)
      {
         return From(() => func(arg1, arg2), null);
      }

      public ITask<TReturn> From<TReturn>(Func<TReturn> func, TaskScheduler scheduler)
      {
         return new Task<TReturn>(
            TaskBinding.From(func), scheduler ?? Scheduler);
      }

      public ITask<TReturn> From<TArg1, TReturn>(Func<TArg1, TReturn> func, TArg1 arg1, TaskScheduler scheduler)
      {
         return From(() => func(arg1), scheduler);
      }

      public ITask<TReturn> From<TArg1, TArg2, TReturn>(
         Func<TArg1, TArg2, TReturn> func, TArg1 arg1, TArg2 arg2, TaskScheduler scheduler)
      {
         return From(() => func(arg1, arg2), scheduler);
      }

      #endregion
      
      #region Actions

      public ITask From(Action action)
      {
         return From(action, null);
      }
      
      public ITask From<TArg1>(Action<TArg1> action, TArg1 arg1)
      {
         return From(() => action(arg1), null);
      }

      public ITask From<TArg1, TArg2>(Action<TArg1, TArg2> action, TArg1 arg1, TArg2 arg2)
      {
         return From(() => action(arg1, arg2), null);
      }

      public ITask From(Action action, TaskScheduler scheduler)
      {
         return new Task(TaskBinding.From(action), scheduler ?? Scheduler);
      }

      public ITask From<TArg1>(Action<TArg1> action, TArg1 arg1, TaskScheduler scheduler)
      {
         return From(() => action(arg1), scheduler);
      }

      public ITask From<TArg1, TArg2>(Action<TArg1, TArg2> action, TArg1 arg1, TArg2 arg2, TaskScheduler scheduler)
      {
         return From(() => action(arg1, arg2), scheduler);
      }

      #endregion
   }
}
